package carcassonne.server.websocket.handler;

import carcassonne.lobby.RoomManager;
import carcassonne.user.UserManager;
import carcassonne.utils.StringUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.apache.log4j.Logger;

import java.nio.charset.StandardCharsets;

public class GateHandler extends ChannelInboundHandlerAdapter {

    private static final Logger logger = Logger.getLogger(GateHandler.class);

    private ByteBuf data = null;

    @Override
    public void channelRead(ChannelHandlerContext context, Object message) throws Exception {

        if (message instanceof FullHttpRequest request) {

            HttpHeaders headers = request.headers();

            // 校验token
            String token = headers.get("token");
            if (StringUtils.IsNullOrEmpty(token)) {
                logger.info("no token，close connection...");
                DenyConnect(context, "no token, close connection...");
                return;
            }
            if (!UserManager.GetInstance().IsLoginUser(token)) {
                DenyConnect(context, "not login, close connection...");
                return;
            }

            String roomID = headers.get("roomID");
            RoomManager roomManager = RoomManager.GetInstance();
            if (roomManager.HasPreparedRoom(roomID)) {

            } else if(roomManager.HasRoom(roomID)) {

            } else {
                DenyConnect(context, "not a legal room id，close connection...");
                return;
            }
//            logger.info("new websocket connection: " + roomID);
        } else if (message instanceof TextWebSocketFrame frame) {
            if (!frame.isFinalFragment()) {
                if (data != null && data.refCnt() > 0) data.release();
                ByteBuf buf = frame.content();
                data = context.alloc().buffer(buf.readableBytes());
                data.writeBytes(buf);
                buf.release();
                return;
            }
//            else {
//                if (data != null && data.refCnt() > 0) {
//                    data.release();
//                    data = null;
//                }
//            }
        } else if (message instanceof ContinuationWebSocketFrame frame) {
            if (data == null) return;
            data.writeBytes(frame.content());
            frame.content().release();
            if (frame.isFinalFragment()) {
                context.fireChannelRead(new TextWebSocketFrame(data));
            }
            return;
        } else if (message instanceof PingWebSocketFrame) {
//            logger.info("ping");
        } else if (message instanceof CloseWebSocketFrame) {

        } else {
            logger.info("unknown message type " + message.getClass().getName());
        }
        super.channelRead(context, message);
    }

    private void DenyConnect(ChannelHandlerContext context, String message) {
        logger.info("deny connect");
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN,
                Unpooled.wrappedBuffer(message.getBytes(StandardCharsets.UTF_8)));
        context.write(response).addListener(ChannelFutureListener.CLOSE);
        context.flush();
    }
}
